using System;
using System.Collections.Generic;
using ProtoModels;
using UnityEngine;

public class MultiplayerLayer : MonoBehaviour
{
	public enum GameType
	{
		Server = 0,
		Client = 1,
		FindMatch = 2
	}

	protected struct MyState
	{
		public bool isHandShakeSent;

		public bool isHandShakeReceived;

		public bool isAskResponseReceived;

		public bool isServer;

		public int clientRetries;

		public bool clientPicketUpAddress;

		public float serverTimeoutTime;

		public float waitingPollTime;

		public bool isTesting;

		public string clientName;

		public bool createdRoom;

		public bool triedToJoinRoom;

		public bool isNetworkAvailable;

		public MatchParameters.MatchParams.MultiplayerParams p;

		public bool introAnimFinished;

		public float questionsTimer;

		public bool shownQuestions;
	}

	public UILabel text;

	protected float serverTimeout = 10f;

	protected string supportRoomNameGUID;

	private float lobbyTimer;

	public GameObject createOrJoinGameScreen;

	public GameObject joinGameScreen;

	public GameObject createGameScreen;

	public string arenaName;

	public UILabel gameName;

	public UILabel joinGameName;

	protected bool joinedToLobby;

	private MyState state;

	protected int maxClientRetries = 10;

	protected GameType gameType;

	protected StandardDeserializer deserializer = new StandardDeserializer();

	private float introTimeStamp;

	private Action delegateWhenJoinedToLobby;

	private bool isCutsceneFinished;

	private string pid = string.Empty;

	private void Awake()
	{
		introTimeStamp = Time.timeSinceLevelLoad + UnityEngine.Random.Range(0f, 10f);
		deserializer.onIntro = OnIntro;
		PhotonNetwork.CrcCheckEnabled = true;
	}

	private void OnEnable()
	{
		TableTennisMainNavigation tableTennisMainNavigation = NavigationManager.instance as TableTennisMainNavigation;
		if (tableTennisMainNavigation != null)
		{
			tableTennisMainNavigation.SetHeader(TableTennisMainNavigation.HeaderType.None);
		}
		tableTennisMainNavigation.characterView.ShowCharacter();
		tableTennisMainNavigation.characterView.ShowView(CharacterDisplayView.ViewType.NameSelectView, false);
		createOrJoinGameScreen.SetActive(false);
		joinGameScreen.SetActive(false);
		createGameScreen.SetActive(false);
		gameType = GameType.FindMatch;
		lobbyTimer = 0f;
		GGPlayerSettings instance = GGPlayerSettings.instance;
		if (instance.Model.version < 1)
		{
			instance.UpdateModel();
		}
		DoOnEnable();
		Screen.sleepTimeout = -1;
		Ads.instance.hideBanner(true);
		if (!GGSupportMenu.instance.isNetworkConnected())
		{
			TableTennisDialog.instance.ShowOk("No internet connection", "Internet connection is needed for multiplayer! Please connect to the internet and try again.", "Ok", delegate
			{
				NavigationManager.instance.Pop();
				NavigationManager.instance.Pop();
			});
		}
	}

	private void DoOnEnable()
	{
		supportRoomNameGUID = RoomName() + Guid.NewGuid().ToString();
		isCutsceneFinished = false;
		GGSupportMenu instance = GGSupportMenu.instance;
		state = default(MyState);
		if (!instance.isNetworkConnected())
		{
			state.isNetworkAvailable = false;
			text.text = "You need to be connected to a network...";
			return;
		}
		GGPlayerSettings instance2 = GGPlayerSettings.instance;
		GGNetwork instance3 = GGNetwork.instance;
		instance3.StopServer();
		instance3.onMessageReceived -= OnNetworkMessage;
		instance3.onMessageReceived += OnNetworkMessage;
		joinedToLobby = false;
		delegateWhenJoinedToLobby = null;
		GameType gameType = this.gameType;
		if (gameType == GameType.FindMatch)
		{
			instance3.Start(ConfigBase.instance.GetMatchServerAppName());
		}
		text.text = "PLAY WITH FRIENDS";
		createOrJoinGameScreen.SetActive(true);
		joinGameScreen.SetActive(false);
		createGameScreen.SetActive(false);
	}

	private void OnDisable()
	{
		Debug.Log("Disable Lobby Layer");
		TableTennisMainNavigation tableTennisMainNavigation = NavigationManager.instance as TableTennisMainNavigation;
		GGNetwork instance = GGNetwork.instance;
		instance.onMessageReceived -= OnNetworkMessage;
		Ads.instance.hideBanner(false);
		delegateWhenJoinedToLobby = null;
		joinedToLobby = false;
	}

	private void OnNetworkMessage(GGNetwork network)
	{
		Debug.Log("Message in lobby layer");
		if (!state.isHandShakeReceived)
		{
			network.PollMessage(deserializer);
		}
	}

	private void OnIntro(MIntro intro)
	{
		Debug.Log("OnIntro");
		if (state.isHandShakeReceived)
		{
			return;
		}
		Debug.Log("OnIntro");
		if (introTimeStamp == intro.timeStamp)
		{
			introTimeStamp = Time.timeSinceLevelLoad + UnityEngine.Random.Range(0f, 20f);
			Debug.Log("Resend Intro");
			SendIntro();
			return;
		}
		if (!state.isHandShakeSent)
		{
			Debug.Log("Send Hand shake");
			SendIntro();
		}
		bool flag = introTimeStamp > intro.timeStamp;
		int num = ((!flag) ? 1 : 0);
		Debug.Log("myServerTag: " + num);
		MIntro mIntro = CreateIntro();
		MIntro intro2 = mIntro;
		MatchParameters.MatchParams.ShoeParams shoeParams = default(MatchParameters.MatchParams.ShoeParams);
		shoeParams.moveSpeed = intro.remoteMoveSpeed;
		shoeParams.jumpSpeed = intro.remoteJumpSpeed;
		shoeParams.shotsToMinSpeed = intro.remoteShotsToMinSpeed;
		shoeParams.normalizedVisualSpeed = intro.normalizedVisualSpeed;
		shoeParams.shoesId = intro.shoeId;
		MatchParameters.MatchParams.ShoeParams remoteShoe = shoeParams;
		state.p = new MatchParameters.MatchParams.MultiplayerParams
		{
			opponentName = intro.myName,
			opponentFlag = intro.myFlag,
			activeTag = num,
			eloRank = intro.eloRank,
			multiplayerWins = intro.multiplayerWins,
			multiplayerLoses = intro.multiplayerLoses,
			roomType = MultiplayerRoomType.Training,
			opponentLevel = intro.level,
			opponentCoins = intro.opponentCoins,
			multiplayerVersion = intro.version,
			intro = intro2,
			supportRoomNameGUID = ((!flag) ? intro.supportRoomNameGUID : supportRoomNameGUID),
			racketId = intro.remoteRacketId,
			remoteShoe = remoteShoe,
			remoteLookGender = intro.remoteLookGender,
			remoteLooks = intro.remoteLooks,
			remoteSkills = new RemoteStats(intro.remoteSkills, remoteShoe.normalizedVisualSpeed, intro.remoteRacketId),
			useRoomParams = false,
			arenaName = arenaName,
			player2Pid = intro.opponentPid,
			opponentImageUrl = intro.opponentImageUrl,
			isRematch = false
		};
		state.isHandShakeReceived = true;
		isCutsceneFinished = true;
	}

	private string RoomName()
	{
		return ConfigBase.instance.GetMatchServerAppName();
	}

	private void OnJoinedLobby()
	{
		Debug.Log("Joined Lobby");
		joinedToLobby = true;
		Action action = delegateWhenJoinedToLobby;
		if (delegateWhenJoinedToLobby != null)
		{
			delegateWhenJoinedToLobby = null;
			action();
		}
	}

	private void OnPhotonJoinRoomFailed()
	{
		Debug.Log("OnPhotonJoinRoomFailed");
		TableTennisDialog.instance.ShowOk("Can't connect to the match", "Can't connect to the match number, please check Match Number and try again", "Ok", null);
		OnJoinRoomSelect();
	}

	public void OnCreateRoom()
	{
		Debug.Log("Creating room");
		text.text = "Creating room...";
		createOrJoinGameScreen.SetActive(false);
		joinGameScreen.SetActive(false);
		createGameScreen.SetActive(false);
		StartCoroutine(BehaviourSingletonInit<GGServerRequestsBackend>.instance.GetPlayerId(delegate(GGServerRequestsBackend.ServerRequest request)
		{
			if (request.status == GGServerRequestsBackend.ServerRequest.RequestStatus.Success)
			{
				string text = request.GetResponse<Pid>().pid;
				CreateMatch(text);
			}
		}));
	}

	private void CreateMatch(string pid)
	{
		createOrJoinGameScreen.SetActive(false);
		joinGameScreen.SetActive(false);
		createGameScreen.SetActive(true);
		UITools.ChangeText(gameName, pid);
		delegateWhenJoinedToLobby = delegate
		{
			text.text = "MATCH CREATED";
			string roomName = RoomName() + pid;
			GGNetwork.instance.JoinOrCreateRoom(roomName);
		};
		if (joinedToLobby)
		{
			delegateWhenJoinedToLobby();
			delegateWhenJoinedToLobby = null;
		}
	}

	private void JoinMatch(string pid)
	{
		delegateWhenJoinedToLobby = delegate
		{
			string roomName = RoomName() + pid;
			GGNetwork.instance.JoinRoom(roomName);
		};
		if (joinedToLobby)
		{
			delegateWhenJoinedToLobby();
			delegateWhenJoinedToLobby = null;
		}
	}

	public void OnJoinRoomSelect()
	{
		text.text = "JOIN MATCH";
		createOrJoinGameScreen.SetActive(false);
		joinGameScreen.SetActive(true);
		createGameScreen.SetActive(false);
	}

	private bool stringHasNonNumberCharacters(string str)
	{
		foreach (char c in str)
		{
			if (c < '0' || c > '9')
			{
				return true;
			}
		}
		return false;
	}

	public void OnJoinRoomSubmit()
	{
		string text = joinGameName.text.Trim().Replace("\n", string.Empty);
		if (stringHasNonNumberCharacters(text))
		{
			if (string.IsNullOrEmpty(text) || text.StartsWith("Enter Match Number"))
			{
				TableTennisDialog.instance.ShowOk("Invalid match number", "Match Number should not be empty! Please enter a Match Number.", "Ok", null);
			}
			else
			{
				TableTennisDialog.instance.ShowOk("Invalid match number", "Match Number should contain only numbers!", "Ok", null);
			}
			joinGameName.text = "Enter Match Number";
		}
		else
		{
			this.text.text = "JOINING MATCH " + text + "...";
			createOrJoinGameScreen.SetActive(false);
			joinGameScreen.SetActive(false);
			createGameScreen.SetActive(false);
			JoinMatch(text);
		}
	}

	private void Update()
	{
		lobbyTimer += Time.deltaTime;
		if (NavigationManager.instance.shouldGoBack)
		{
			OnBack();
			return;
		}
		if (state.isNetworkAvailable)
		{
			if (GGSupportMenu.instance.isNetworkConnected())
			{
				DoOnEnable();
			}
			return;
		}
		if (pid != string.Empty && isCutsceneFinished)
		{
			isCutsceneFinished = false;
			state.p.player1Pid = pid;
			BehaviourSingleton<ScreenNavigation>.instance.LoadMultiplayerMatch(state.p, null);
			Analytics.instance.ReportMultiplayerGameMatch("FriendRoom");
		}
		GGNetwork instance = GGNetwork.instance;
		if (instance.isInError())
		{
			text.text = "Error with the connection, retry later...";
			return;
		}
		if (instance.ConnectedPlayers() <= 0 && state.isHandShakeSent)
		{
			DoOnEnable();
		}
		if (!state.isHandShakeReceived)
		{
			if (instance.ConnectedPlayers() > 0 && !state.isHandShakeSent)
			{
				text.text = "Found an opponent!";
				SendIntro();
				Debug.Log("opponent");
			}
			instance.PollMessage(deserializer);
		}
	}

	private MIntro CreateIntro()
	{
		StoreItemsConfig.StoreItem usedItem = StoreItemsConfig.instance.GetUsedItem(StoreItemsConfig.StoreItem.ItemType.Shoe);
		StoreItemsConfig.StoreItem usedItem2 = StoreItemsConfig.instance.GetUsedItem(StoreItemsConfig.StoreItem.ItemType.Racket);
		int opponentCoins = GGPlayerSettings.instance.walletManager.CurrencyCount(MultiplayerRooms.instance.multiplayerCurrencyType);
		string playerName = BehaviourSingletonInit<FriendProfilesManager>.instance.PlayerName;
		MIntro result = default(MIntro);
		result.version = 4;
		result.timeStamp = introTimeStamp;
		result.myName = playerName;
		result.myFlag = GGPlayerSettings.instance.Model.flag;
		result.eloRank = GGPlayerSettings.instance.GetDisplayEloRatingInt();
		result.multiplayerWins = GGPlayerSettings.instance.Model.multiplayerWins;
		result.multiplayerLoses = GGPlayerSettings.instance.Model.multiplayerLoses;
		result.level = GGPlayerSettings.instance.Level();
		result.opponentCoins = opponentCoins;
		result.supportRoomNameGUID = supportRoomNameGUID;
		result.remoteMoveSpeed = usedItem.moveSpeed;
		result.remoteJumpSpeed = usedItem.jumpSpeed;
		result.remoteShotsToMinSpeed = usedItem.shotsToMinSpeed;
		result.normalizedVisualSpeed = usedItem.NormalizedVisualSpeed();
		result.remoteRacketId = usedItem2.id;
		result.remoteLookGender = GGPlayerSettings.instance.Model.genderSelect;
		result.remoteLooks = ((GGPlayerSettings.instance.Model.look == null) ? new List<CharacterLookProperty>() : GGPlayerSettings.instance.Model.look);
		result.remoteSkills = ((GGPlayerSettings.instance.Model.skills == null) ? new List<SkillLevel>() : GGPlayerSettings.instance.Model.skills);
		result.opponentImageUrl = ((!GGPlayerSettings.instance.useProfilePictureInMultiplayer || BehaviourSingletonInit<FriendProfilesManager>.instance.myProfile == null) ? string.Empty : BehaviourSingletonInit<FriendProfilesManager>.instance.myProfile.pictureUrl);
		result.shoeId = usedItem.id;
		return result;
	}

	private void SendIntro()
	{
		GGNetwork network = GGNetwork.instance;
		state.isHandShakeSent = true;
		MIntro intro = CreateIntro();
		if (pid != string.Empty)
		{
			DoSendIntro(intro, network);
			return;
		}
		StartCoroutine(BehaviourSingletonInit<GGServerRequestsBackend>.instance.GetPlayerId(delegate(GGServerRequestsBackend.ServerRequest request)
		{
			if (request.status == GGServerRequestsBackend.ServerRequest.RequestStatus.Success)
			{
				pid = request.GetResponse<Pid>().pid;
				DoSendIntro(intro, network);
			}
			else
			{
				TableTennisDialog.instance.ShowOk("No server connection", "Couldn't connect to the server", "Ok", delegate
				{
					NavigationManager.instance.Pop();
					NavigationManager.instance.Pop();
				});
			}
		}));
	}

	private void DoSendIntro(MIntro intro, GGNetwork network)
	{
		intro.opponentPid = pid;
		intro.Send(network);
	}

	public void OnBack()
	{
		GGNetwork.instance.StopServer();
		NavigationManager.instance.Pop();
	}

	private void OnApplicationPause(bool paused)
	{
		if (paused)
		{
			OnDisable();
		}
		else
		{
			OnEnable();
		}
	}
}
